/**
 * This class takes care of cell values drag and drop. This will help users to simply drag and drop if he finds that the
 * column values are not properly aligned. Column values will not be properly aligned if scripts used for imports are
 * inconsistent in terms of the number of columns they have. Columns can also become misaligned because if user chooses
 * to parse individual column values by delimiters before creating a table. The algorithm of drag and drop currently is
 * barely minimum and has a scope of adding sophistication. Selected cells are converted into comma-separated strings
 * which are later split into an array and moved to the drop location cell and the consecutive rows in the same column.
 * This also means that regardless of the geometry of selection (vertical, horizontal or block) cells will always be
 * moved to the cells where the drop occurred. So, the behavior when the selection of cells doesn't belong to a single
 * columns (i.e. the cell selection is not vertical) is undefined
 */
package slhs.tempo.TableAnalyzer;

import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.io.IOException;

import javax.swing.JComponent;
import javax.swing.JTable;
import javax.swing.TransferHandler;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;

/**
 * CellsTRansferHandler.java
 * 
 * @author Swapnil Devikar
 * @version beta
 * 
 */
public class CellsTransferHandler extends TransferHandler {

    @Override
    public int getSourceActions(JComponent c) {
	return DnDConstants.ACTION_COPY_OR_MOVE;

    }

    @Override
    public Transferable createTransferable(JComponent comp) {
	JTable table = (JTable) comp;
	StringBuffer cellValuesString = new StringBuffer();
	String value = null;
	StringSelection transferable = null;
	TableModel model = table.getModel();
	int[] rows = table.getSelectedRows();
	int[] columns = table.getSelectedColumns();
	for (int columnIndex = 0; columnIndex < columns.length; columnIndex++) {
	    for (int rowIndex = 0; rowIndex < rows.length; rowIndex++) {
		value = (String) model.getValueAt(rows[rowIndex], columns[columnIndex]);
		cellValuesString.append(value + ",");
		transferable = new StringSelection(cellValuesString.toString());
		// the following can be done when drop is competed in a dedicated method
		// table.getModel().setValueAt(null, rows[rowIndex], columns[columnIndex]);
	    }
	}
	return transferable;
    }

    @Override
    public boolean canImport(TransferHandler.TransferSupport info) {
	if (!info.isDataFlavorSupported(DataFlavor.stringFlavor)) {
	    return false;
	}
	return true;
    }

    @Override
    public boolean importData(TransferSupport support) {

	if (!support.isDrop()) {
	    System.out.println("not supported");

	    return false;
	}

	if (!canImport(support)) {
	    System.out.println("Cannot import once again");

	    return false;
	}

	JTable table = (JTable) support.getComponent();
	DefaultTableModel tableModel = (DefaultTableModel) table.getModel();

	JTable.DropLocation dl = (JTable.DropLocation) support.getDropLocation();

	int row = dl.getRow();
	int col = dl.getColumn();

	String data;
	String[] cellValues;
	try {
	    data = (String) support.getTransferable().getTransferData(DataFlavor.stringFlavor);
	    cellValues = data.split(",");
	} catch (UnsupportedFlavorException e) {
	    System.out.println("Unsupported flavor");
	    return false;
	} catch (IOException e) {
	    System.out.println("IO exception");
	    return false;
	}

	for (int rowIndex = 0; rowIndex < cellValues.length; rowIndex++) {
	    tableModel.setValueAt(cellValues[rowIndex], row + rowIndex, col);
	}

	return true;
    }

    @Override
    protected void exportDone(JComponent source, Transferable data, int action) {
	JTable sourceTable = (JTable) source;
	int[] selectedRows = sourceTable.getSelectedRows();
	int[] selectedColumns = sourceTable.getSelectedColumns();
	for (int columnIndex = 0; columnIndex < selectedColumns.length; columnIndex++) {
	    for (int rowIndex = 0; rowIndex < selectedRows.length; rowIndex++) {
		sourceTable.setValueAt(null, selectedRows[rowIndex], selectedColumns[columnIndex]);
	    }
	}

    }
}
